package com.fizzgate.config;

import com.alipay.sofa.ark.spi.model.Biz;
import com.fizzgate.service.PluginService;
import com.fizzgate.util.JacksonUtils;
import com.fizzgate.util.NetworkUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class PluginServiceConfig {
    private final static class ServerBizInfo {
        public String serviceName;
        public String ip;
        public int    port;
        public long   ts;

        public Map<String, InstalledBiz> bizs;
    }

    private final static class InstalledBiz {
        public String bizName;
        public String bizVersion;
        public String status;
    }
    @Resource
    private ReactiveWebServerApplicationContext applicationContext;

    @Autowired
    private PluginService pluginService;

    @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
    private ReactiveStringRedisTemplate rt;

    private String hashKey;

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerBizInfo.class);
    @PostConstruct
    public void postConstruct() {
        ConfigurableEnvironment env = applicationContext.getEnvironment();
        stat.serviceName = env.getProperty("spring.application.name");
        stat.ip          = NetworkUtils.getServerIp();
        stat.port        = Integer.parseInt(env.getProperty("server.port", "8600"));
        hashKey          = stat.ip + ':' + stat.port;
    }
    private static final String fizz_gateway_bizs = "fizz_gateway_bizs";
    private PluginServiceConfig.ServerBizInfo stat = new PluginServiceConfig.ServerBizInfo();

    // 上报节点biz运行状态
    @Scheduled(cron = "${fizz-gateway-biz-stat-sched.cron:*/1 * * * * ?}")
    public void sched() {
        stat.ts = System.currentTimeMillis();

        String s;
        try {
            Map<String, Biz> startedBizs = pluginService.STARTED_BIZS;
            stat.bizs = new HashMap<String , InstalledBiz>();
            startedBizs.forEach((name, biz)->{
                InstalledBiz installedBiz = new InstalledBiz();
                installedBiz.bizName = biz.getBizName();
                installedBiz.bizVersion = biz.getBizVersion();
                installedBiz.status = biz.getBizState().getBizState();
                stat.bizs.put(name, installedBiz);
            });
            s = JacksonUtils.writeValueAsString(stat);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("gateway installed: {}", s);
            }
        } catch (RuntimeException e) {
            LOGGER.error("serial fizz gateway node installed biz error", e);
            return;
        }
        rt.opsForHash().put(fizz_gateway_bizs, hashKey, s)
                .doOnError(
                        t -> {
                            LOGGER.error("report fizz gateway node installed biz error", t);
                        }
                )
                .block();
    }
}
